#include <stdio.h>

#include "od_engine.h"
#include "od_framework.h"
#include "sip_param.h"
#include "rpc_response.h"
#include "ipmisc.h"
#include "usecase_sip.h"

static char software_date[32] = "Build@"__DATE__" "__TIME__;
static char software_version[32] = "od-sip/V1.0.0";

#define USER_PARAM_END {NULL, 0, 0, 0, "", 0, 0, JSPARA_ARG_NULL, NULL}

#define UNUSE_PARAM(param)   (void)param

static void act_get_int_param(od_task_handle h, 
                                uint32_t param_id, 
                                void *mem,
                                char *task_name)
{
    enum {MAX_STRING_LEN = 32};
    char check_str[MAX_STRING_LEN] = {0};

    UNUSE_PARAM(task_name);
    
    od_task_get_para(h, param_id, &check_str);
    *(int32_t *)mem = check_str;
}

static void act_get_str_param(od_task_handle h, 
                                uint32_t param_id, 
                                void *mem,
                                char *task_name)
{
    enum {MAX_STRING_LEN = 32};
    char check_str[MAX_STRING_LEN] = {0};

    UNUSE_PARAM(task_name);
    
    od_task_get_para(h, OD_SIP_HANDLE_EVENT_USERNAME, check_str);
    strncpy((char *)mem, check_str, MAX_STRING_LEN);
}


static int32_t act_set_str_param(od_task_handle h, 
                                   uint32_t param_id, 
                                   void *mem,
                                   char *task_name)
{
    enum {MAX_STRING_LEN = 32};
    char *value_str = NULL;
    char check_str[MAX_STRING_LEN] = {0};
    
    value_str = (char *)mem;
    od_task_set_para(h, param_id, value_str);
    od_task_app(h);
    od_task_get_para(h, param_id, check_str);
    if (strcmp(value_str, check_str) != 0) {
        strncpy((char *)mem, check_str, MAX_STRING_LEN);
        RPTERR("tsk:[%s] param_id:[%d] set error!!!", 
                    task_name, param_id);
        return OD_ERROR;
    }

    return OD_OK;
}

static int32_t act_set_int_param(od_task_handle h, 
                                   uint32_t param_id, 
                                   void *mem,
                                   char *task_name)
{
    enum {MAX_STRING_LEN = 32};
    char *value_str = NULL;
    char check_str[MAX_STRING_LEN] = {0};
    
    value_str = *(int *)mem;
    od_task_set_para(h, param_id, &value_str);
    od_task_app(h);
    od_task_get_para(h, param_id, &check_str);
    if (value_str != check_str)
    {
        *(int *)mem = check_str;
        RPTERR("tsk:[%s] param_id:[%d] set error!!!", 
                        task_name, param_id);
        return OD_ERROR;
    }

    return OD_OK;
}


static int32_t act_sip_register_params(void *var_hdl, int offset, void *mem, char *task_name)
{
    od_framework_t * framework = var_hdl;
    int ret = OD_OK;
    od_task_handle h = ghash_find(framework->task_table, task_name);
    
    if (NULL == h) {
        RPTWRN("tsk[%s] can not found in task_table", task_name);
        return OD_ERROR;
    }
    
    RPTDBG("Act %s params, offset %d, mem %d", task_name, offset, *(int32_t *)mem);
    switch (offset)
    {
        case OFFSET(od_sip_register_dynamic_params, username):
            ret = act_set_str_param(h, OD_SIP_REG_UEERNAME, mem, task_name);
            break;
            
        case OFFSET(od_sip_register_dynamic_params, passwd):
            ret = act_set_str_param(h, OD_SIP_REG_PASSWD, mem, task_name);
            break;
          
        case OFFSET(od_sip_register_dynamic_params, proxy_addr):
            ret = act_set_str_param(h, OD_SIP_REG_PROXY_ADDR, mem, task_name);
            break;  
             
        case OFFSET(od_sip_register_dynamic_params, proxy_port):
            ret = act_set_int_param(h, OD_SIP_REG_PROXY_PORT, mem, task_name);
            break;
            
        case OFFSET(od_sip_register_dynamic_params, expires):     
            ret = act_set_int_param(h, OD_SIP_REG_EXPIRES, mem, task_name);
            break;

        case OFFSET(od_sip_register_dynamic_params, proxy_id):
            ret = act_set_str_param(h, OD_SIP_REG_PROXY_ID, mem, task_name);
            break;

        case OFFSET(od_sip_register_dynamic_params, proxy_domain):
            ret = act_set_str_param(h, OD_SIP_REG_PROXY_DOMAIN, mem, task_name);
            break;
            
        //read only
        case OFFSET(od_sip_register_dynamic_params, reg_status):
            act_get_int_param(h, OD_SIP_REG_REG_STATUS, mem, task_name);
            break; 
            
         default:
            RPTERR("unknown %s params!!", task_name);
            break;
    }
    
    return ret;
}

static int32_t act_sip_register_0_params(void *var_hdl, int offset, void *mem, int id)
{
    UNUSE_PARAM(id);
    return act_sip_register_params(var_hdl, offset, mem, TSK_NAME_SIP_REIGSTER);
}

static int32_t act_sip_register_1_params(void *var_hdl, int offset, void *mem, int id)
{
    UNUSE_PARAM(id);
    return act_sip_register_params(var_hdl, offset, mem, TSK_NAME_SIP_REIGSTER2);
}

static int32_t act_sip_invite_params(void *var_hdl, int offset, void *mem, int id)
{
    od_framework_t * framework = var_hdl;
    int ret = OD_OK;
    char *task_name = TSK_NAME_SIP_INVITE;
    od_task_handle h = ghash_find(framework->task_table, task_name);
    
    if (NULL == h) {
        RPTWRN("tsk[%s] can not found in task_table", task_name);
        return OD_ERROR;
    }
    
    RPTDBG("Act %s params, offset %d, mem %d, id %d",task_name, offset, *(int32_t *)mem, id);    
    switch (offset)
    {
        case OFFSET(od_sip_invite_dynamic_params, dst_uri):
            ret = act_set_str_param(h, OD_SIP_INVITE_DST_URI, mem, task_name);
            break;
            
        case OFFSET(od_sip_invite_dynamic_params, bye_flg):
            ret = act_set_int_param(h, OD_SIP_INVITE_BYE_FLG, mem, task_name);
            break;
          
        case OFFSET(od_sip_invite_dynamic_params, send_invite_flg):
            ret = act_set_int_param(h, OD_SIP_INVITE_SEND_INVITE_FLG, mem, task_name);
            break;  
             
        //read only
        case OFFSET(od_sip_invite_dynamic_params, invite_status):
            act_get_int_param(h, OD_SIP_INVITE_INVITE_STATUS, mem, task_name);
            break; 
            
         default:
            RPTERR("unknown %s params!!", task_name);
            break;
    }
    
    return ret;
}


static int32_t act_sip_handle_event_params(void *var_hdl, int offset, void *mem, int id)
{
    od_framework_t * framework = var_hdl;
    int ret = OD_OK;
    char *task_name = TSK_NAME_SIP_HANDLE_EVENT;
    od_task_handle h = ghash_find(framework->task_table, task_name);
    
    if (NULL == h) {
        RPTWRN("tsk[%s] can not found in task_table", task_name);
        return OD_ERROR;
    }

    RPTDBG("Act %s params, offset %d, mem %d, id %d", task_name, offset, *(int32_t *)mem, id);
    switch (offset)
    {
        case OFFSET(od_sip_handle_event_dynamic_params, request_status):
            act_get_int_param(h, OD_SIP_HANDLE_EVENT_REQUEST_STATUS, mem, task_name);
            break;
            
        case OFFSET(od_sip_handle_event_dynamic_params, username):
            act_get_str_param(h, OD_SIP_HANDLE_EVENT_USERNAME, mem, task_name);
            break;
          
        case OFFSET(od_sip_handle_event_dynamic_params, bye_flg):
            ret = act_set_int_param(h, OD_SIP_HANDLE_EVENT_BYE_FLG, mem, task_name);
            break; 
            
         default:
            RPTERR("unknown %s params!!", task_name);
            break;
    }
    
    return ret;
}


static int32_t act_sip_state_machine_params(void *var_hdl, int offset, void *mem, int id)
{
    od_framework_t * framework = var_hdl;
    int ret = OD_OK;
    char *task_name = TSK_NAME_SIP_STATE_MACHINE;
    od_task_handle h = ghash_find(framework->task_table, task_name);
    
    if (NULL == h) {
        RPTWRN("tsk[%s] can not found in task_table", task_name);
        return OD_ERROR;
    }

    RPTDBG("Act %s params, offset %d, mem %d, id %d", task_name, offset, *(int32_t *)mem, id);
    switch (offset)
    {
        case OFFSET(od_sip_state_machine_dynamic_params, phone_status):
            act_get_int_param(h, OD_SIP_STATE_MACHINE_PHONE_STATUS, mem, task_name);
            break;
            
        case OFFSET(od_sip_state_machine_dynamic_params, time_cnt):
            act_get_str_param(h, OD_SIP_STATE_MACHINE_TIME_CNT, mem, task_name);
            break;
            
         default:
            RPTERR("unknown %s params!!", task_name);
            break;
    }
    
    return ret;
}

#define SIP_REGISTER_PARAMS_ARRAY(chn) \
    struct pjdesc pd_sip_register_##chn##_params[] = {\
    {PT_STRI_, 0, 1, OFFSET(od_sip_register_dynamic_params, username),   "username", SIP_NORMAL_ARRAY_SIZE, 0, JSPARA_ARG_STR(DEFAULT_USER_NAME), act_sip_register_##chn##_params},\
    {PT_STRI_, 0, 1, OFFSET(od_sip_register_dynamic_params, passwd),     "passwd", SIP_NORMAL_ARRAY_SIZE, 0, JSPARA_ARG_STR(DEFAULT_PASSWD), act_sip_register_##chn##_params},\
    {PT_STRI_, 0, 1, OFFSET(od_sip_register_dynamic_params, proxy_addr), "proxy_addr", SIP_NORMAL_ARRAY_SIZE, 0, JSPARA_ARG_STR(DEFAULT_PROXY_ADDR), act_sip_register_##chn##_params},\
    {PT_SINT_, 0, 1, OFFSET(od_sip_register_dynamic_params, proxy_port), "proxy_port", sizeof(int), 0, JSPARA_ARG_S32(5060, 0, 65535), act_sip_register_##chn##_params},\
    {PT_SINT_, 0, 1, OFFSET(od_sip_register_dynamic_params, expires),    "expires", sizeof(int), 0, JSPARA_ARG_S32(60, 0, 6000), act_sip_register_##chn##_params},\
    {PT_SINT_ | PT_FMT_RDONLY, 0, 1, OFFSET(od_sip_register_dynamic_params, reg_status), "reg_status", sizeof(int), 0, JSPARA_ARG_S32(REGISTER_FAILED, REGISTER_FAILED, REGISTER_STATUS_NUMS), act_sip_register_##chn##_params},\
    {PT_STRI_, 0, 1, OFFSET(od_sip_register_dynamic_params, proxy_id),     "proxy_id",    SIP_NORMAL_ARRAY_SIZE, 0, JSPARA_ARG_STR("3401212121"), act_sip_register_##chn##_params},\
    {PT_STRI_, 0, 1, OFFSET(od_sip_register_dynamic_params, proxy_domain), "proxy_domain", SIP_NORMAL_ARRAY_SIZE, 0, JSPARA_ARG_STR("34012"), act_sip_register_##chn##_params},\
    USER_PARAM_END\
    };\
hash_desc_t param_sip_register_##chn = \
{\
    .pjdesc = pd_sip_register_##chn##_params,\
    .hash_tab = NULL,\
}

SIP_REGISTER_PARAMS_ARRAY(0);
SIP_REGISTER_PARAMS_ARRAY(1);

struct pjdesc pd_sip_invite_params[] = {
    {PT_SINT_, 0, 1, OFFSET(od_sip_invite_dynamic_params, dst_uri),         "dst_uri", 64, 0, JSPARA_ARG_STR("123456789"), act_sip_invite_params},
    {PT_SINT_, 0, 1, OFFSET(od_sip_invite_dynamic_params, invite_status),   "invite_status", sizeof(int), 0, JSPARA_ARG_S32(OD_YES, OD_NO, OD_YES), act_sip_invite_params},
    {PT_SINT_, 0, 1, OFFSET(od_sip_invite_dynamic_params, bye_flg),         "bye_flg", sizeof(int), 0, JSPARA_ARG_S32(OD_YES, OD_NO, OD_YES), act_sip_invite_params},
    {PT_SINT_, 0, 1, OFFSET(od_sip_invite_dynamic_params, send_invite_flg), "send_invite_flg", sizeof(int), 0, JSPARA_ARG_S32(OD_YES, OD_NO, OD_YES), act_sip_invite_params},
    USER_PARAM_END
};
hash_desc_t param_sip_invite_param = 
{
    .pjdesc = pd_sip_invite_params,
    .hash_tab = NULL,
};

struct pjdesc pd_sip_handle_event_params[] = {
    {PT_SINT_, 0, 1, OFFSET(od_sip_handle_event_dynamic_params, request_status),  "request_status", sizeof(int), 0, JSPARA_ARG_S32(OD_YES, OD_NO, OD_YES), act_sip_handle_event_params},
    {PT_SINT_, 0, 1, OFFSET(od_sip_handle_event_dynamic_params, username),        "username", 32, 0, JSPARA_ARG_STR("123456789"), act_sip_handle_event_params},
    {PT_SINT_, 0, 1, OFFSET(od_sip_handle_event_dynamic_params, bye_flg),         "bye_flg", sizeof(int), 0, JSPARA_ARG_S32(OD_YES, OD_NO, OD_YES), act_sip_handle_event_params},
    USER_PARAM_END
};
hash_desc_t param_sip_handle_event_param = 
{
    .pjdesc = pd_sip_handle_event_params,
    .hash_tab = NULL,
};

struct pjdesc pd_sip_state_machine_params[] = {
    {PT_SINT_, 0, 1, OFFSET(od_sip_state_machine_dynamic_params, phone_status),  "phone_status", sizeof(int), 0, JSPARA_ARG_S32(OD_YES, OD_NO, OD_YES), act_sip_state_machine_params},
    {PT_SINT_, 0, 1, OFFSET(od_sip_state_machine_dynamic_params, time_cnt),      "time_cnt", 128, 0, JSPARA_ARG_STR("00:00:00"), act_sip_state_machine_params},
    USER_PARAM_END
};
hash_desc_t param_sip_state_machine_param = 
{
    .pjdesc = pd_sip_state_machine_params,
    .hash_tab = NULL,
};

struct pjdesc pd_usrset_sip[] = {
    {PT_STRU_, 0, 1, OFFSET(usr_sip_params, sip_register[0]), "sip_register", sizeof(od_sip_register_dynamic_params), (size_t)&param_sip_register_0, JSPARA_ARG_NULL, NULL},
    {PT_STRU_, 0, 1, OFFSET(usr_sip_params, sip_register[1]), "sip_register_1", sizeof(od_sip_register_dynamic_params), (size_t)&param_sip_register_1, JSPARA_ARG_NULL, NULL},
    {PT_STRU_, 0, 1, OFFSET(usr_sip_params, sip_invite), "sip_invite", sizeof(od_sip_invite_dynamic_params), (size_t)&param_sip_invite_param, JSPARA_ARG_NULL, NULL},
    {PT_STRU_, 0, 1, OFFSET(usr_sip_params, sip_state_machine), "sip_state_machine", sizeof(od_sip_state_machine_dynamic_params), (size_t)&param_sip_state_machine_param, JSPARA_ARG_NULL, NULL},
    {PT_STRU_, 0, 1, OFFSET(usr_sip_params, sip_handle_event), "sip_handle_event", sizeof(od_sip_handle_event_dynamic_params), (size_t)&param_sip_handle_event_param, JSPARA_ARG_NULL, NULL}, 
    USER_PARAM_END
};


static int usrset_sip_params_init(usr_sip_params *user)
{
    int ret = 0;
    int i = 0;

    OD_SIP_ASSERT_RETURN(user, OD_ERROR);
      
    /*read only*/
    strncpy(user->version, software_version, OD_MAX_OBJ_NAME - 1); //版本
    strncpy(user->date, software_date, OD_MAX_OBJ_NAME - 1);  //编译日期

    /*如果想要结束进程，设置exit变量，在其act响应函数中操作done，控制进程结束*/
    user->exit = OD_OFF;
    user->done = OD_OFF;

    return ret;
}


int sip_params_init(od_framework_t *frameworks, char *filename)
{
    jsparam_args_t args;
    sip_params_obj * params_obj = (sip_params_obj *)(frameworks->param_table);

    OD_SIP_ASSERT_RETURN(frameworks && filename, OD_ERROR);

    usrset_sip_params_init(&(params_obj->sip_params));
    RPTDBG("after usrset_params_init");

    od_mutex_init(&(params_obj->timer_ref_mutex));

    params_obj->usr_ptr = NULL;
    
    /****************json handle init, include  system json and usrset json table**********/
    args.mempt = &(params_obj->sip_params);
    args.pjdesc = pd_usrset_sip;
    args.prj_hdl = frameworks;
    params_obj->sip_json_hdl = jsparam_create(&args);
    
    if(NULL == params_obj->sip_json_hdl)
    {
        RPTERR("params_obj->sip_json_hdl create error!!");
        return OD_ERROR;
    }
    RPTDBG("after jsparam_create");
    memset(params_obj->sip_json_filename, 0, OD_MAX_PATH_LEN);    
    strncpy(params_obj->sip_json_filename, filename, OD_MAX_PATH_LEN - 1);
    jsparam_load(params_obj->sip_json_hdl, params_obj->sip_json_filename);
    jsparam_sav(params_obj->sip_json_hdl, params_obj->sip_json_filename);
    
    return OD_OK;
}

/*_*/

